package horde.internalResources.horrorControl.HCvis;

import horde.internalResources.HorrorControl.HCvis.components.LockedTable;
import horde.internalResources.HorrorControl.HCvis.components.TablePanel;
import horde.internalResources.HorrorControl.HorrorControl;
import horde.internalResources.dictionaries.dictionary;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Scanner;
import java.util.StringTokenizer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

/**
 * Component that manages the display of the traces generated by the platform
 * @author Arturo Mazón and Andres Picazo
 */
public class tracesPanel extends JPanel implements ActionListener {

    // <editor-fold defaultstate="collapsed" desc="Singleton">
    public static JPanel getInstance(HorrorControl hc) {

        if (instance == null) {
            instance = new tracesPanel(hc);
        }
        return instance;
    }

    public tracesPanel() {
        super();
        hc = HorrorControl.getInstance();
        createElements();
        organizeElements();
        crearMouseListener();
        list.addMouseListener(mouseListener);
        this.setSize(tamPanel);
        this.setVisible(true);
    }

    public tracesPanel(HorrorControl hc) {
        super();
        this.hc = hc;
        createElements();
        organizeElements();
        crearMouseListener();
        list.addMouseListener(mouseListener);
        this.setSize(tamPanel);
        this.setVisible(true);
    }

    // </editor-fold>

    /**
     * Creates all the components necessary to build the graphic interface
     */
    private void createElements() {
        list = new JList();
        tracesTable = new TablePanel();         
        tracesRevolution.setEnabled(false);

        tracesTable.setTableModel(crearModeloTabla());
        tracesPList = new JPanel(new BorderLayout());
        DefaultListModel modelL = listModel();
        list.setModel(modelL);

        list.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                tracesTable.setFilterText(list.getSelectedValue().toString());
                tracesTable.updateFilter();
            }
        });
        tracesPList.setPreferredSize(new Dimension(100, 500));
        labelListDebug.setForeground(Color.blue);
        tracesPList.add(labelListDebug, BorderLayout.PAGE_START);
        tracesPList.add(list, BorderLayout.CENTER);
        tracesPList.add(tracesRevolution, BorderLayout.PAGE_END);
        tracesRevolution.addActionListener(this);
    }

    /**
     * Places properly each component in the graphic interface
     */
    private void organizeElements() {
        this.setLayout(new BorderLayout());
        this.add(tracesPList, BorderLayout.WEST);
        this.add(tracesTable, BorderLayout.CENTER);
    }

    // <editor-fold defaultstate="collapsed" desc="Listeners">
    /**
     * One of the method that implements the listener for the list of agents. Simple selection
     */
    private void crearMouseListener() {
        mouseListener = new MouseListener() {

            public void mouseClicked(MouseEvent e) {
                // Detecto doble click
                if (e.getClickCount() == 2) {
                    TablePanel panelDeTrazas = new TablePanel();
                    panelDeTrazas.setTableModel(tracesTable.getTableModel());
                    panelDeTrazas.setCurrentFilter(list.getSelectedValue().toString());
                    panelDeTrazas.filterField.setEnabled(false);
                    JFrame f = new JFrame(list.getSelectedValue().toString());
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.setLayout(new BorderLayout());
                    f.add(panelDeTrazas, BorderLayout.CENTER);
                    f.setVisible(true);
                    f.setSize(400, 300);
                    f.setLocationRelativeTo(null);
                }
            }

            public void mousePressed(MouseEvent e) {
            }

            public void mouseReleased(MouseEvent e) {
            }

            public void mouseEntered(MouseEvent e) {
            }

            public void mouseExited(MouseEvent e) {
            }
        };
    }

    /**
     *Class/method that implements the listener for the list of agents. Multiselect
     */
    protected class SharedListSelectionHandler implements ListSelectionListener {

        public void valueChanged(ListSelectionEvent e) {
            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
            String s = "";
            if (lsm.isSelectionEmpty()) {
                tracesTable.setFilterText(s);
                tracesTable.updateFilter();
            } else {
                // Find out which indexes are selected.
                int minIndex = lsm.getMinSelectionIndex();
                int maxIndex = lsm.getMaxSelectionIndex();

                for (int i = minIndex; i <= maxIndex; i++) {
                    if (lsm.isSelectedIndex(i)) {
                        s = s + tracesTable.filterField.getText().toString() + " ";
                    }
                    tracesTable.setFilterText(s);
                    tracesTable.updateFilter();
                }
            }
        }
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="List of agents management">
    /**
     * Creates a standard model for the list of agents that have traced something
     * @return DefaultListModel
     */
    private DefaultListModel listModel() {
        DefaultListModel modelL = new DefaultListModel();
        Object[] agents = hc.getAgents();
        for (int i = 0; i < agents.length; i++) {
            modelL.addElement(agents[i]);
        }
        return modelL;
    }

    /**
     * Adds a new agent to the list of agents in the graphic interface
     * @param o Agent given
     */
    public void setJListModel(Object o) {
        if (!list.getModel().toString().contains((String) o)) {
            DefaultListModel modelL = (DefaultListModel) list.getModel();
            modelL.addElement(o);
            list.setModel(modelL);
        }
    }

    // </editor-fold>
    
    /**
     * Creates a standard model for the table of traces
     *
     */
    private DefaultTableModel crearModeloTabla() {
        String[] columns = {dictionary.getString("hc.field1TracesKeeper"), dictionary.getString("hc.field2TracesKeeper"),
                            dictionary.getString("hc.field3TracesKeeper"), dictionary.getString("hc.field4TracesKeeper")};
        return new DefaultTableModel(null, columns);
    }

    /**
     * Adds a complete trace (src,msg,lvl,ts) to the table of traces
     * @param data Complete trace to show
     */
    public void addTrace(String[] data) {
        DefaultTableModel t = (DefaultTableModel) tracesTable.getTableModel();
        try {
            t.addRow(data);
            setJListModel(data[0]);
        } catch (Exception e) {
            // Este metodo a veces genera excepciones, pero se arreglan al actualizarse,
            // asi que aqui mejor no poner nada porque solo lleva a errores
            System.err.printf("Size:%d\n", data.length);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="Traces Revolution">
    /**
     * Swap the visibility of the button "Loader" when necessary.
     */
    public void enableLoader() {
        tracesRevolution.setEnabled(!tracesRevolution.isEnabled());
    }

    /**
     * Method that implements the action listener of the botton named "loader". It loads an old traces file and show it.
     * @param e Action performed
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == tracesRevolution) {
            JFileChooser fc = new JFileChooser();
            fc.setCurrentDirectory(new File("src/horde/logs"));
            int option = fc.showOpenDialog(this);

            if (option == JFileChooser.APPROVE_OPTION) {
                try {
                    File f = fc.getSelectedFile();
                    if (f.isFile() && f.canRead()) {
                        Scanner scanner = new Scanner(fc.getSelectedFile());
//                        scanner.skip("\\-*+");
                        scanner.nextLine();
                        scanner.nextLine();
                        scanner.nextLine();
//                        scanner.skip("\\-*+");
                        while (scanner.hasNextLine()) {
                            String s = scanner.nextLine();
                            String[] data = new String[4];
                            StringTokenizer st = new StringTokenizer(s, "|");
                            int c = 0;
                            while (st.hasMoreTokens()) {
                                data[c++] = st.nextToken().trim();
                            }
                            if (c != 0) {
                                addTrace(data);
                            }
                            scanner.skip("\\-*+");
                        }
                    }
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Atributes">
    protected JList list;
    private JLabel labelListDebug = new JLabel(dictionary.getString("hcVis.labelListDebug"));
    private JPanel tracesPList;
    private JButton tracesRevolution = new JButton(dictionary.getString("hcVis.buttonLoader"));;
    protected LockedTable tableModel;
    protected TablePanel tracesTable;
    private static HorrorControl hc = null;
    protected MouseListener mouseListener;
    private Dimension tamPanel = new Dimension(400, 500);
    private static tracesPanel instance = null;
    // </editor-fold>
}
